package com.ff.xyh.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import io.minio.*;
import io.minio.messages.Item;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @Auther FF
 * @Date 2022年 10月 24日
 * @Time 14:18
 */

public class MinioUtils {

    /**
     * 删除一个对象
     *
     * @param bucketName 存储桶名称
     * @param objectName 存储桶里的对象名称
     */
    @SneakyThrows
    public static boolean deleteObject(MinioClient minioClient, String bucketName, String objectName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 删除文件目录下的所有文件
     *
     * @param dir 文件目录
     * @return 删除结果
     * @throws Exception
     */
    public static List<Object> deleteDir(MinioClient minioClient, String bucketName, String dir) throws Exception{

        List<Object> list = new ArrayList<>();
        List<Object> files = getFiles(minioClient, bucketName, dir);
        String format = "{isSuccess:\"%s\", objectName:\"%s\", size:\"%s\"}";
        for (Object file : files) {
            Gson gson = new Gson();
            HashMap map = gson.fromJson(file.toString(), HashMap.class);
            String objectName = map.get("objectName").toString();
            boolean isSuccess = deleteObject(minioClient, bucketName, objectName);
            list.add(JSON.parse(String.format(format, isSuccess, objectName, map.get("fileSize").toString())));
        }
        return list;
    }

    /**
     * 递归获取某路径下的所有文件，文件夹，并输出
     */
    public static List<Object> getFiles(MinioClient minioClient, String bucketName, String objectName) throws Exception {
        List<Object> list = new ArrayList<>();

        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder()
                        .bucket(bucketName)
                        .prefix(objectName)
                        .build());

        String format = "{objectName:\"%s\",fileSize:\"%s\"}";

        for (Result<Item> result : results) {
            Item item = result.get();
            if (item.isDir()) {
                List<Object> files = getFiles(minioClient, bucketName, item.objectName());
                list.addAll(files);
            } else {
                list.add(JSON.parse(String.format(format, item.objectName(), calFileSize(0, item.size()))));
            }
        }
        return list;
    }

    /**
     * 获取要下载的文件的输入流 可以复制到响应体输出流也可以用文件输出流保存到本地
     * @param minioClient
     * @param bucketName
     * @param objectName
     * @return
     * @throws Exception
     */
    public static InputStream downloadFile(MinioClient minioClient, String bucketName, String objectName) throws Exception {
        InputStream in = null;
        try {
            in = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return in;
        }
    }
    public static StatObjectResponse getStatObjectResponse(MinioClient minioClient, String bucketName, String objectName) throws Exception {
        return minioClient.statObject(
                StatObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build());
    }

    /**
     * 单个文件上传 指定路径文件名
     * @param minioClient
     * @param bucketName
     * @param pathAndFilename
     * @param file
     * @return
     */
    public static Boolean uploadFile(MinioClient minioClient, String bucketName, String pathAndFilename, MultipartFile file) {
        Boolean isSuccess = false;
        InputStream in = null;
        try {
            in = file.getInputStream();
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(pathAndFilename)
                            .stream(in, file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build());
            isSuccess = true;
        } catch (Exception e) {
            e.printStackTrace();
            isSuccess = false;
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return isSuccess;
        }
    }

    /**
     * 单个文件上传
     * @param minioClient
     * @param bucketName
     * @param path
     * @param file
     * @param saveFileName
     * @return
     */
    public static Boolean uploadFile(MinioClient minioClient, String bucketName, String path, MultipartFile file, String saveFileName) {
        // 最后一个字符不是 '/'
        if (path.lastIndexOf('/') != path.length()-1)
            path = path + "/";
        return uploadFile(minioClient, bucketName, path + saveFileName, file);
    }

    /**
     * 计算文件单位和长度
     * @param level 从Byte单位开始 传0即可 从 kB 开始 传1 以此类推
     * @param fileSize
     * @return
     */
    public static String calFileSize (int level, long fileSize) {
        double realSize = fileSize;
        if (fileSize > Math.pow(1000,level+1))
        {
            return calFileSize(++level , fileSize);
        } else {
            switch (level) {
                case 1 :
                    realSize = fileSize/1000.0;
                    return realSize + " KiB";
                case 2 :
                    realSize = fileSize/1000000.0;
                    return realSize + " MiB";
                case 3 :
                    realSize = fileSize/1000000000.0;
                    return realSize + " GiB";
                case 4 :
                    realSize = fileSize/1000000000000.0;
                    return realSize + " TiB";
                case 5 :
                    realSize = fileSize/1000000000000000.0;
                    return realSize + " PiB";
                default:
                    return realSize + " B";
            }
        }
    }

    /**
     * 获取文件后缀名
     * @param filename
     * @return
     */
    public static String getFileSuffix (String filename) {
        return filename.substring(filename.lastIndexOf('.'));
    }
    /**
     * 获取 当前时间 加 后缀名
     * @param filename
     * @return
     */
    public static String getFileDateName (String filename) {
        return DateTimeUtil.stampToTime(System.currentTimeMillis())
                + getFileSuffix(filename);
    }


}
